<template>
	<div id="user-manage-view">
		<!-- 搜索表单 -->
		<div class="search-section">
			<a-form layout="inline" :model="searchParams" @finish="doSearch" class="search-form">
				<a-form-item label="用户ID">
					<a-input v-model:value="searchParams.id" placeholder="输入用户ID" allow-clear />
				</a-form-item>
				<a-form-item label="账号">
					<a-input v-model:value="searchParams.userAccount" placeholder="输入账号" allow-clear />
				</a-form-item>
				<a-form-item label="用户名">
					<a-input v-model:value="searchParams.userName" placeholder="输入用户名" allow-clear />
				</a-form-item>
				<a-form-item>
					<a-space>
						<a-button type="primary" html-type="submit">搜索</a-button>
						<a-button type="default" @click="resetSearch">重置</a-button>
						<a-button type="primary" @click="showAddModal">
							<PlusOutlined />
							新增用户
						</a-button>
					</a-space>
				</a-form-item>
			</a-form>
		</div>

		<!-- 表格 -->
		<div class="table-section">
			<a-table
				:columns="columns"
				:data-source="dataList"
				:pagination="pagination"
				@change="doTableChange"
				:loading="loading"
			>
			<template #bodyCell="{ column, record }">
				<template v-if="column.dataIndex === 'id'">
					<span class="chat-id">{{ record.id }}</span>
				</template>
				<template v-else-if="column.dataIndex === 'userAvatar'">
					<div class="avatar-cell">
						<a-avatar 
							:src="record.userAvatar || kunkunImg" 
							:size="40" 
							class="admin-user-avatar clickable-avatar" 
							@click="showAvatarPreview(record.userAvatar || kunkunImg)"
						>
							{{ !record.userAvatar ? record.userName?.[0]?.toUpperCase() : '' }}
						</a-avatar>
					</div>
				</template>
				<template v-else-if="column.dataIndex === 'userRole'">
					<a-tag :color="getRoleColor(record.userRole)">
						{{ getRoleText(record.userRole) }}
					</a-tag>
					<SimpleVipBadge :vip-expire-time="record.vipExpireTime" :user-role="record.userRole" />
				</template>
				<template v-if="column.dataIndex === 'userProfile'">
					<span style="white-space: pre-wrap; word-break: break-all; max-width: 200px; display: inline-block">
						{{ record.userProfile }}
					</span>
				</template>
				<template v-if="column.dataIndex === 'createTime'">
					{{ dayjs(record.createTime).format('YYYY-MM-DD HH:mm:ss') }}
				</template>
				<template v-else-if="column.key === 'action'">
					<a-space>
						<a-button type="primary" size="small" @click="showEditModal(record)"> 编辑 </a-button>
						<a-button danger size="small" @click="doDelete(record.id)"> 删除 </a-button>
					</a-space>
				</template>
			</template>
		</a-table>
		</div>

		<!-- 新增/编辑用户弹窗 -->
		<a-modal
			v-model:open="modalVisible"
			:title="isEdit ? '编辑用户' : '新增用户'"
			:confirmLoading="modalLoading"
			@ok="handleModalOk"
			@cancel="handleModalCancel"
			width="600px"
		>
			<a-form ref="formRef" :model="userForm" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
				<a-form-item
					label="用户账号"
					name="userAccount"
					:rules="[
						{ required: true, message: '请输入用户账号!' },
						{ min: 4, message: '账号长度不能少于4位!' },
					]"
				>
					<a-input v-model:value="userForm.userAccount" placeholder="请输入用户账号" :disabled="isEdit" />
				</a-form-item>

				<a-form-item label="用户名" name="userName" :rules="[{ required: true, message: '请输入用户名!' }]">
					<a-input v-model:value="userForm.userName" placeholder="请输入用户名" />
				</a-form-item>
				<a-form-item label="用户头像" name="userAvatar">
					<div class="avatar-upload-container">
						<div class="avatar-preview">
							<a-avatar v-if="userForm.userAvatar" :src="userForm.userAvatar" :size="80" class="admin-form-avatar" />
							<a-avatar v-else :size="80" style="background-color: #52c41a" class="admin-form-avatar">
								{{ userForm.userName?.[0]?.toUpperCase() || '?' }}
							</a-avatar>
							<div v-if="avatarUploading" class="avatar-loading">
								<a-spin size="small" />
							</div>
						</div>
						<div class="avatar-actions">
							<a-tabs v-model:active-key="avatarUploadMode" type="card" size="small">
								<a-tab-pane key="file" tab="本地上传">
									<a-upload
										:show-upload-list="false"
										:before-upload="beforeAvatarUpload"
										:custom-request="handleAvatarUpload"
										accept="image/jpeg,image/jpg,image/png"
									>
										<a-button size="small" :loading="avatarUploading">
											<UploadOutlined />
											{{ avatarUploading ? '上传中...' : '上传头像' }}
										</a-button>
									</a-upload>
								</a-tab-pane>
								<a-tab-pane key="url" tab="URL上传">
									<UrlPictureUpload :pictureUrl="userForm.userAvatar" :onSuccess="handleUrlUploadSuccess" />
								</a-tab-pane>
							</a-tabs>
							<a-button v-if="userForm.userAvatar" size="small" danger @click="clearAvatar" style="margin-top: 8px">
								清除头像
							</a-button>
						</div>
						<div class="avatar-tips">
							<a-typography-text type="secondary" style="font-size: 12px">
								支持 JPG、PNG 格式，文件大小不超过 2MB
							</a-typography-text>
						</div>
					</div>
				</a-form-item>

				<a-form-item label="用户简介" name="userProfile">
					<a-textarea
						v-model:value="userForm.userProfile"
						placeholder="请输入用户简介"
						:rows="3"
						:max-length="200"
						show-count
					/>
				</a-form-item>

				<a-form-item label="用户角色" name="userRole" :rules="[{ required: true, message: '请选择用户角色!' }]">
					<a-select v-model:value="userForm.userRole" placeholder="请选择用户角色">
						<a-select-option value="user">普通用户</a-select-option>
						<a-select-option value="admin">管理员</a-select-option>
					</a-select>
				</a-form-item>
			</a-form>
		</a-modal>

		<!-- 头像预览模态框 -->
		<a-modal
			v-model:open="previewVisible"
			:footer="null"
			:width="800"
			:centered="true"
			@cancel="handlePreviewCancel"
			class="image-preview-modal"
		>
			<template #title>
				<span>头像预览</span>
			</template>
			<div class="preview-image-container">
				<img :src="previewImage" alt="头像预览" class="preview-image" />
			</div>
		</a-modal>
	</div>
</template>

<script lang="ts" setup>
import { deleteUser, listUserVoByPage, addUser, updateUser, uploadPictureByFile } from '@/api/userController'
import { message, Modal } from 'ant-design-vue'
import { computed, onMounted, reactive, ref } from 'vue'
import { ExclamationCircleOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons-vue'
import { createVNode } from 'vue'
import dayjs from 'dayjs'
import ACCESS_ENUM from '@/access/accessEnum'
import UrlPictureUpload from '@/components/picture/UrlPictureUpload.vue'
import SimpleVipBadge from '@/components/SimpleVipBadge.vue'
import kunkunImg from '@/assets/kunkun.png'

// 表格加载状态
const loading = ref(false)

// 头像预览相关
const previewVisible = ref(false)
const previewImage = ref('')

// 弹窗相关状态
const modalVisible = ref(false)
const modalLoading = ref(false)
const isEdit = ref(false)
const formRef = ref()
const avatarUploading = ref(false)
const avatarUploadMode = ref('file') // 头像上传模式：file 或 url

// 用户表单数据
const userForm = reactive<{
	id?: number
	userAccount?: string
	userName?: string
	userAvatar?: string
	userProfile?: string
	userRole?: string
}>({})

// 获取角色颜色
const getRoleColor = (role?: string) => {
	const colorMap: Record<string, string> = {
		[ACCESS_ENUM.NOT_LOGIN]: 'default',
		[ACCESS_ENUM.USER]: 'blue',
		vip: 'gold',
		[ACCESS_ENUM.ADMIN]: 'red',
	}
	return colorMap[role || ACCESS_ENUM.NOT_LOGIN]
}

// 获取角色文本
const getRoleText = (role?: string) => {
	const textMap: Record<string, string> = {
		[ACCESS_ENUM.NOT_LOGIN]: '未登录',
		[ACCESS_ENUM.USER]: '普通用户',
		vip: 'VIP用户',
		[ACCESS_ENUM.ADMIN]: '管理员',
	}
	return textMap[role || ACCESS_ENUM.NOT_LOGIN]
}

// 显示新增弹窗
const showAddModal = () => {
	isEdit.value = false
	modalVisible.value = true
	// 重置表单
	Object.assign(userForm, {
		id: undefined,
		userAccount: '',
		userName: '',
		userAvatar: '',
		userProfile: '',
		userRole: ACCESS_ENUM.USER,
	})
}

// 显示编辑弹窗
const showEditModal = (record: API.UserVO) => {
	isEdit.value = true
	modalVisible.value = true
	// 填充表单数据
	Object.assign(userForm, {
		id: record.id,
		userAccount: record.userAccount,
		userName: record.userName,
		userAvatar: record.userAvatar,
		userProfile: record.userProfile,
		userRole: record.userRole,
	})
}

// 弹窗确认
const handleModalOk = async () => {
	try {
		await formRef.value.validate()
		modalLoading.value = true

		if (isEdit.value) {
			// 编辑用户
			const res = await updateUser({
				id: userForm.id,
				userName: userForm.userName,
				userAvatar: userForm.userAvatar,
				userProfile: userForm.userProfile,
				userRole: userForm.userRole,
			})
			if (res.data.code === 0) {
				message.success('编辑用户成功')
				modalVisible.value = false
				await fetchData()
			} else {
				message.error('编辑用户失败：' + res.data.message)
			}
		} else {
			// 新增用户
			const res = await addUser({
				userAccount: userForm.userAccount,
				userName: userForm.userName,
				userAvatar: userForm.userAvatar,
				userProfile: userForm.userProfile,
				userRole: userForm.userRole,
			})
			if (res.data.code === 0) {
				message.success('新增用户成功')
				modalVisible.value = false
				await fetchData()
			} else {
				message.error('新增用户失败：' + res.data.message)
			}
		}
	} catch (error) {
		console.error('表单验证失败:', error)
	} finally {
		modalLoading.value = false
	}
}

// 弹窗取消
const handleModalCancel = () => {
	modalVisible.value = false
	// 重置上传状态
	avatarUploading.value = false
	// 重置表单验证
	formRef.value?.resetFields()
}

// 头像上传前检查
const beforeAvatarUpload = (file: File) => {
	const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'
	if (!isJpgOrPng) {
		message.error('只能上传 JPG/PNG 格式的图片!')
		return false
	}
	const isLt2M = file.size / 1024 / 1024 < 2
	if (!isLt2M) {
		message.error('图片大小不能超过 2MB!')
		return false
	}
	return true
}

// 处理头像上传
const handleAvatarUpload = async ({ file }: any) => {
	avatarUploading.value = true
	try {
		// 创建FormData
		const formData = new FormData()
		formData.append('file', file)

		// 使用图片上传接口上传头像
		const res = await uploadPictureByFile({}, file)
		const responseData: any = res.data
		if (responseData.code === 0 && responseData.data) {
			// 上传成功，更新用户头像
			userForm.userAvatar = responseData.data
			message.success('头像上传成功！')
		} else {
			message.error('头像上传失败：' + responseData.message)
		}
	} catch (error: any) {
		console.error('头像上传失败', error)
		message.error('头像上传失败：' + error.message)
	} finally {
		avatarUploading.value = false
	}
}

// 清除头像
const clearAvatar = () => {
	userForm.userAvatar = ''
	message.success('头像已清除')
}

// 处理URL上传成功
const handleUrlUploadSuccess = (pictureUrl: string) => {
	userForm.userAvatar = pictureUrl
	message.success('头像上传成功！')
}
// 表单列
const columns = [
	{ title: '用户编号', dataIndex: 'id', align: 'center' },
	{ title: '账号', dataIndex: 'userAccount', align: 'center' },
	{ title: '用户名', dataIndex: 'userName', align: 'center' },
	{ title: '头像', dataIndex: 'userAvatar', align: 'center' },
	{ title: '简介', dataIndex: 'userProfile', align: 'center' },
	{ title: '用户角色', dataIndex: 'userRole', align: 'center' },
	{ title: '创建时间', dataIndex: 'createTime', align: 'center' },
	{ title: '操作', key: 'action', align: 'center' },
]

// 表单数据
const dataList = ref<API.UserVO[]>([])
const total = ref(0)

// 搜索条件
const searchParams = reactive<API.UserQueryRequest>({
	current: 1,
	pageSize: 10,
	sortField: 'createTime',
	sortOrder: 'ascend',
	id: undefined,
})

// 分页参数
const pagination = computed(() => {
	return {
		current: searchParams.current ?? 1,
		pageSize: searchParams.pageSize ?? 10,
		total: total.value,
		showSizeChanger: true,
		showTotal: (total: number) => `总共 ${total} 条`,
	}
})

// 表格变化之后，重新获取数据
const doTableChange = (page: { current: number; pageSize: number }) => {
	searchParams.current = page.current
	searchParams.pageSize = page.pageSize
	fetchData()
}

// 获取数据
const fetchData = async () => {
	try {
		const res: any = await listUserVoByPage({
			...searchParams,
		})
		if (res.data.code === 0 && res.data.data) {
			dataList.value = res.data.data.records ?? []
			total.value = res.data.data.total || 0
		} else {
			message.error('获取数据失败：' + res.data.message)
		}
	} catch {
		message.error('网络错误，请稍后再试')
	}
}

// 搜索操作
const doSearch = () => {
	// 重置当前页为1
	searchParams.current = 1
	// 重新获取数据
	fetchData()
}

// 重置搜索条件
const resetSearch = () => {
	// 清空搜索条件
	searchParams.id = undefined
	searchParams.userAccount = ''
	searchParams.userName = ''
	// 重置当前页为1
	searchParams.current = 1
	// 重新获取数据
	fetchData()
}

// 删除操作
const doDelete = async (id: number) => {
	if (!id) {
		return
	}

	Modal.confirm({
		title: '确认删除',
		icon: createVNode(ExclamationCircleOutlined),
		content: '确定要删除这个用户吗？此操作不可恢复！',
		okText: '确认',
		cancelText: '取消',
		async onOk() {
			try {
				const res = await deleteUser({ id })
				if (res.data.code === 0) {
					message.success('删除成功')
					// 删除成功后重新获取数据
					await fetchData()
				} else {
					message.error('删除失败：' + res.data.message)
				}
			} catch {
				message.error('删除失败，请重试')
			}
		},
	})
}

/**
 * 显示头像预览
 * @param avatarUrl 头像URL
 */
const showAvatarPreview = (avatarUrl: string) => {
	previewImage.value = avatarUrl
	previewVisible.value = true
}

/**
 * 关闭头像预览
 */
const handlePreviewCancel = () => {
	previewVisible.value = false
	previewImage.value = ''
}

// 页面加载时获取数据，请求一次
onMounted(() => {
	// 初始化数据
	fetchData()
})
</script>

<style scoped lang="scss">
#user-manage-view {
	max-width: 100%;
	overflow-x: hidden;

	// 表头标题居中
	:deep(.ant-table-thead > tr > th) {
		text-align: center !important;
	}

	// 全部表单内容居中展示
	:deep(.ant-table-tbody > tr > td) {
		text-align: center !important;
	}

	.chat-id {
		font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
		color: #1890ff;
		font-weight: 600;
		font-size: 13px;
		background: #f0f8ff;
		padding: 4px 8px;
		border-radius: 4px;
		display: inline-block;
	}

	// 搜索区域样式
	.search-section {
		background: white;
		padding: 20px 24px;
		margin-bottom: 0;
		border-radius: 8px 8px 0 0;
		border: 1px solid #e8e8e8;
		border-bottom: none;
		box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);

		.search-form {
			display: flex;
			align-items: center;
			flex-wrap: wrap;
			gap: 16px;

			:deep(.ant-form-item) {
				margin-bottom: 0;
				margin-right: 0;
				display: flex;
				align-items: center;

				.ant-form-item-label {
					padding-right: 8px;
					width: auto;
					flex-shrink: 0;

					label {
						color: #333;
						font-size: 14px;
						font-weight: normal;
						margin-bottom: 0;
					}
				}

				.ant-form-item-control {
					flex: 1;
					min-width: 0;
				}
			}
		}
	}

	// 表格区域样式
	.table-section {
		background: white;
		border: 1px solid #e8e8e8;
		border-radius: 0 0 8px 8px;
		box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
		padding: 0;
	}

	// 头像上传组件样式
	.avatar-upload-container {
		.avatar-preview {
			position: relative;
			display: inline-block;
			margin-bottom: 12px;

			.avatar-loading {
				position: absolute;
				top: 0;
				left: 0;
				right: 0;
				bottom: 0;
				background: rgba(255, 255, 255, 0.8);
				display: flex;
				align-items: center;
				justify-content: center;
				border-radius: 50%;
			}
		}

		.avatar-actions {
			display: flex;
			gap: 8px;
			margin-bottom: 12px;
		}

		.avatar-input {
			margin-bottom: 8px;
		}

		.avatar-tips {
			font-size: 12px;
		}
	}
}

.admin-user-avatar {
	border: 2px solid #ff8c00 !important;
	box-shadow: 0 2px 8px rgba(255, 140, 0, 0.3) !important;
	transition: all 0.3s ease !important;
	
	&:hover {
		border-color: #ff7700 !important;
		box-shadow: 0 4px 12px rgba(255, 140, 0, 0.4) !important;
		transform: translateY(-1px) !important;
	}

	&.clickable-avatar {
		cursor: pointer;
		
		&:hover {
			transform: translateY(-1px) scale(1.05) !important;
		}
	}
}

// 头像预览模态框样式
.image-preview-modal {
	:deep(.ant-modal-content) {
		border-radius: 12px;
		overflow: hidden;
	}

	.preview-image-container {
		display: flex;
		justify-content: center;
		align-items: center;
		padding: 20px;
		background: #f5f5f5;
		border-radius: 8px;

		.preview-image {
			max-width: 100%;
			max-height: 500px;
			border-radius: 8px;
			box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
		}
	}
}

.admin-form-avatar {
	border: 2px solid #ff8c00 !important;
	box-shadow: 0 2px 8px rgba(255, 140, 0, 0.3) !important;
	transition: all 0.3s ease !important;
	
	&:hover {
		border-color: #ff7700 !important;
		box-shadow: 0 4px 12px rgba(255, 140, 0, 0.4) !important;
		transform: translateY(-1px) !important;
	}
}
</style>
